package org.dxy.domain.model.aggregate.impl;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.dxy.domain.command.material.*;
import org.dxy.domain.event.DomainEvent;
import org.dxy.domain.event.material.*;
import org.dxy.domain.model.aggregate.Material;
import org.dxy.domain.model.valueobject.MaterialId;
import org.dxy.domain.model.valueobject.MaterialStatus;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * 物料聚合根实现
 * @author dxy
 * @createTime 2025/9/7
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class MaterialAggRoot implements Material {

    /** 物料ID值对象 */
    private MaterialId materialId;
    
    /** 物料编码 */
    private String materialCode;

    /** 物料规格 */
    private String specification;
    
    /** 计量单位 */
    private String unit;
    
    /** 标准成本 */
    private BigDecimal standardCost;
    
    /** 物料状态值对象 */
    private MaterialStatus status;
    
    /** 领域事件列表 */
    @Builder.Default
    private List<DomainEvent> domainEvents = new ArrayList<>();

    /**
     * 创建物料
     */
    public static Material create(Long materialId, CreateMaterialCommand command) {
        MaterialAggRoot material = MaterialAggRoot.builder()
                .materialId(MaterialId.of(materialId))
                .materialCode(command.materialCode())
                .status(MaterialStatus.active())
                .build();

        // 发布物料创建事件
        material.addDomainEvent(new MaterialCreatedEvent(
                materialId,
                command.materialCode()));

        return material;
    }

    @Override
    public void update(UpdateMaterialCommand command) {
    }

    @Override
    public void updateSpecification(UpdateMaterialSpecificationCommand command) {
        String oldSpecification = this.specification;
        this.specification = command.newSpecification();

        // 发布规格变更事件
        addDomainEvent(new MaterialSpecificationChangedEvent(
                this.materialId.value(),
                oldSpecification,
                command.newSpecification()
        ));
    }

    @Override
    public void updateUnit(UpdateMaterialUnitCommand command) {
        String oldUnit = this.unit;
        this.unit = command.newUnit();

        // 发布单位变更事件
        addDomainEvent(new MaterialUnitChangedEvent(
                this.materialId.value(),
                oldUnit,
                command.newUnit()
        ));
    }

    @Override
    public void updateCost(UpdateMaterialCostCommand command) {
        BigDecimal oldCost = this.standardCost;
        this.standardCost = command.newCost();

        // 发布成本更新事件
        addDomainEvent(new MaterialCostUpdatedEvent(
                this.materialId.value(),
                oldCost,
                command.newCost()
        ));
    }

    @Override
    public void enable(EnableMaterialCommand command) {
        this.status = MaterialStatus.active();

        // 发布启用事件
        addDomainEvent(new MaterialEnabledEvent(this.materialId.value()));
    }

    @Override
    public void disable(DisableMaterialCommand command) {
        this.status = MaterialStatus.disabled();

        // 发布停用事件
        addDomainEvent(new MaterialDisabledEvent(this.materialId.value()));
    }

    @Override
    public void delete(DeleteMaterialCommand command) {
        this.status = MaterialStatus.deleted();

        // 发布删除事件
        addDomainEvent(new MaterialDeletedEvent(this.materialId.value()));
    }

    @Override
    public List<DomainEvent> getDomainEvents() {
        return this.domainEvents;
    }

    @Override
    public void clearDomainEvents() {
        this.domainEvents.clear();
    }

    @Override
    public boolean hasDomainEvents() {
        return !domainEvents.isEmpty();
    }

    @Override
    public boolean hasNoDomainEvents() {
        return domainEvents.isEmpty();
    }

    @Override
    public void addDomainEvent(DomainEvent event) {
        this.domainEvents.add(event);
    }
}